package br.ufsc.ctc.ine5622.compilador.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.filechooser.FileNameExtensionFilter;

import br.ufsc.ctc.ine5622.compilador.Main;
import br.ufsc.ctc.ine5622.compilador.arquivo.Extensao;

/**
 * Main Window of the program.
 * 
 * @author Paulo Pinho
 * @author William di Domenico
 * 
 */
public class JanelaPrincipal extends JFrame implements ActionListener {
	private static final long serialVersionUID = 1L;

	/**
	 * Reference to the control component.
	 */
	private Main main;

	/* GUI components */
	private JEditorPane textArea = new JEditorPane();
	private JScrollPane textScroll = new JScrollPane(textArea);
	private JMenuBar menuBar = new JMenuBar();
	private JMenu arquivoMenu = new JMenu("Arquivo");
	private JMenu lexicoMenu = new JMenu("Léxico");
	private JMenu sintaticoMenu = new JMenu("Sintático");
	private JMenu semanticoMenu = new JMenu("Semântico");
	private JMenu codigoMenu = new JMenu("Código");
	private JMenu ajudaMenu = new JMenu("Ajuda");
	private JMenuItem abrirItem = new JMenuItem("Abrir");
	private JMenuItem salvarItem = new JMenuItem("Salvar");
	private JMenuItem sairItem = new JMenuItem("Sair");
	private JMenuItem analiseLexicaItem = new JMenuItem("Análise léxica");
	private JMenuItem analiseSintaticaItem = new JMenuItem("Análise sintática");
	private JMenuItem analiseSemanticaItem = new JMenuItem("Análise semantica");
	private JMenuItem ajudaItem = new JMenuItem("Ajuda do compilador");
	private JMenuItem sobreItem = new JMenuItem("Sobre");
	private JFileChooser fileChooser = new JFileChooser();

	public JanelaPrincipal(Main main) {
		super("Compilador");
		this.main = main;
		composeGui();
	}

	/**
	 * Gets the text from the edition field.
	 * 
	 * @return text in the text area
	 */
	public String getText() {
		return textArea.getText();
	}

	/**
	 * Sets a text in the editor field.
	 * 
	 * @param text
	 */
	public void setText(String text) {
		textArea.setText(text);
	}

	/**
	 * Moves the position of the carret in the editor field.
	 * 
	 * @param pos
	 */
	public void setCarretPosition(int pos) {
		textArea.setCaretPosition(pos);
	}

	/**
	 * Shows a pop-up with information to the user.
	 * 
	 * @param message
	 * @param title
	 */
	public void showInfoMsg(Object message, Object title) {
		JOptionPane.showMessageDialog(this, message.toString(), title
				.toString(), JOptionPane.INFORMATION_MESSAGE);
	}

	/**
	 * Shows a pop-up with error messages to the user.
	 * 
	 * @param message
	 * @param title
	 */
	public void showErrorMsg(Object message, Object title) {
		JOptionPane.showMessageDialog(this, message.toString(), title
				.toString(), JOptionPane.ERROR_MESSAGE);
	}

	/**
	 * Handles the composition of GUI components.
	 */
	private void composeGui() {
		addListeners();
		addMenuItems();
		addMenus();
		this.setJMenuBar(menuBar);

		textArea
				.setPreferredSize(new Dimension((int) Toolkit
						.getDefaultToolkit().getScreenSize().getWidth() / 2,
						(int) Toolkit.getDefaultToolkit().getScreenSize()
								.getWidth() * 3 / 8));

		textArea.setBorder(BorderFactory.createLineBorder(Color.WHITE, 5));
		textArea.setFont(new Font("monospaced", Font.PLAIN, 13));

		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setIconImage(new ImageIcon(new File("").getAbsolutePath()
				+ File.separator + "resources" + File.separator + "icon.png")
				.getImage());
		this.setLayout(new BorderLayout());
		this.add(textScroll, BorderLayout.CENTER);
		this.pack();
		this.setVisible(true);
	}

	/**
	 * Adds menu items to its menus
	 */
	private void addMenuItems() {
		arquivoMenu.add(abrirItem);
		arquivoMenu.add(salvarItem);
		arquivoMenu.addSeparator();
		arquivoMenu.add(sairItem);
		lexicoMenu.add(analiseLexicaItem);
		sintaticoMenu.add(analiseSintaticaItem);
		semanticoMenu.add(analiseSemanticaItem);
		ajudaMenu.add(ajudaItem);
		ajudaMenu.add(sobreItem);
	}

	/**
	 * Adds menus to the menu bar.
	 */
	private void addMenus() {
		menuBar.add(arquivoMenu);
		menuBar.add(lexicoMenu);
		menuBar.add(sintaticoMenu);
		menuBar.add(semanticoMenu);
		menuBar.add(codigoMenu);
		menuBar.add(ajudaMenu);
	}

	/**
	 * Add listeners to components that 
	 * handle events.
	 */
	private void addListeners() {
		abrirItem.addActionListener(this);
		salvarItem.addActionListener(this);
		sairItem.addActionListener(this);
		analiseLexicaItem.addActionListener(this);
		analiseSintaticaItem.addActionListener(this);
		analiseSemanticaItem.addActionListener(this);
		ajudaItem.addActionListener(this);
		sobreItem.addActionListener(this);
	}

	/**
	 * Method called when a event happens on the GUI.
	 * It will react according to the source of said
	 * event.  
	 */
	@Override
	public void actionPerformed(ActionEvent event) {
		try {
			if (event.getSource() == abrirItem) {
				fileChooser.resetChoosableFileFilters();
				fileChooser.addChoosableFileFilter(new CustomFileFilter());
				int returnVal = fileChooser
						.showOpenDialog(JanelaPrincipal.this);

				if (returnVal == JFileChooser.APPROVE_OPTION) {
					String conteudo = main.ler(fileChooser.getSelectedFile()
							.getAbsolutePath());
					textArea.setText(conteudo);
				}

			} else if (event.getSource() == salvarItem) {
				fileChooser.resetChoosableFileFilters();

				// Add file filters according to enum
				for (int i = 0; i < Extensao.values().length; i++) {
					Extensao e = Extensao.values()[i];
					fileChooser
							.addChoosableFileFilter(new FileNameExtensionFilter(
									"*." + e.toString().toLowerCase(), e
											.toString()));
				}
				
				int returnVal = fileChooser
						.showSaveDialog(JanelaPrincipal.this);

				if (returnVal == JFileChooser.APPROVE_OPTION) {
					Extensao choosenExtension = Extensao.values()[0];

					for (int i = 1; i < Extensao.values().length; i++) {
						Extensao e = Extensao.values()[i];
						if (fileChooser.accept(new File("a."
								+ e.toString().toLowerCase()))) {
							choosenExtension = e;
						}
					}

					main.salvar(textArea.getText(), fileChooser
							.getSelectedFile().getAbsolutePath(),
							choosenExtension.toString());
				}

			} else if (event.getSource() == sairItem) {
				main.endProgram();

			} else if (event.getSource() == analiseLexicaItem) {
				main.analiseLexica(textArea.getText());

			} else if (event.getSource() == analiseSintaticaItem) {
				main.analiseSintatica(textArea.getText());

			} else if (event.getSource() == analiseSemanticaItem) {
				main.analiseSemantica(textArea.getText());

			} else if (event.getSource() == ajudaItem) {
				new DialogAjuda(this);

			} else if (event.getSource() == sobreItem) {
				new DialogSobre(this);
			}
		} catch (IOException e) {
			e.printStackTrace();
			System.err.println("IO Exception");
		}
	}
}
